package com.gezi.admin.module.code.gentable.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.gezi.admin.module.sys.menu.SysMenuService;
import com.gezi.admin.module.code.gentable.table.CodeGenTableEntity;
import com.gezi.admin.module.code.gentable.column.CodeGenTableColumnEntity;
import com.gezi.admin.module.code.gentable.config.GenConfig;
import com.gezi.admin.module.code.gentable.config.GenConstants;
import com.gezi.admin.utils.AppContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.VelocityContext;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 模板处理工具类
 *
 * @Author 格子软件
 * @createDate 2024/2/10 09:00
 * @contact 公众号：格子软件 微信：13716343106 邮箱：1424529270@qq.com
 */
@Slf4j
public class VelocityUtils {
    /**
     * 项目空间路径
     */
    private static final String PROJECT_PATH = "main/java";

    /**
     * mybatis空间路径
     */
    private static final String MYBATIS_PATH = "main/resources/mapper";

    /**
     * 默认上级菜单，系统工具
     */
    private static final String DEFAULT_PARENT_MENU_ID = "3";

    /**
     * 设置模板变量信息
     *
     * @return 模板列表
     */
    public static VelocityContext prepareContext(CodeGenTableEntity genTable) {
        String packageName = genTable.getPackageName();

        VelocityContext velocityContext = new VelocityContext();
        velocityContext.put("tableName", genTable.getTableName());
        velocityContext.put("tableComment", genTable.getTableComment());
        velocityContext.put("tplCategory", genTable.getTplCategory());
        velocityContext.put("packageName", GenConfig.basePackageName + packageName);
        velocityContext.put("ClassName", StringUtils.capitalize(genTable.getClassName()));
        velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
        velocityContext.put("classRemark", genTable.getClassRemark());
        velocityContext.put("author", genTable.getAuthor());
        velocityContext.put("createTime", DateUtil.format(DateUtil.date(),"yyyy-MM-dd HH:mm:ss"));
        velocityContext.put("contact", "@contact 公众号：格子软件 微信：13716343106 邮箱：1424529270@qq.com");
        velocityContext.put("jiekouPath", genTable.getJiekouPath());

        velocityContext.put("basePackage", getPackagePrefix(packageName));
        velocityContext.put("datetime", DateUtil.date());
        velocityContext.put("importList", getImportList(genTable));//导入包
        velocityContext.put("columns", genTable.getColumns());
        velocityContext.put("table", genTable);
        velocityContext.put("dicts", getDicts(genTable));
        velocityContext.put("tableIsSelect", genTable.getTableIsSelect());
        velocityContext.put("tableIsImport", genTable.getTableIsImport());
        velocityContext.put("tableIsExport", genTable.getTableIsExport());
        velocityContext.put("tableIsQuanxian", genTable.getTableIsQuanxian());
        setMenuVelocityContext(velocityContext, genTable);//生成菜单
        return velocityContext;
    }

    public static void setMenuVelocityContext(VelocityContext context, CodeGenTableEntity genTable) {
        String options = genTable.getOptions();
        JSONObject paramsObj = JSON.parseObject(options);
        String parentMenuId = getParentMenuId(paramsObj);
        context.put("parentMenuId", parentMenuId);
        String menuId = UUID.fastUUID().toString(true);
        context.put("menuId", menuId);
        SysMenuService sysMenuService = AppContextUtil.getBean(SysMenuService.class);
        String menuLevelStr = sysMenuService.getMenuLevelStr(parentMenuId, menuId);
        context.put("menuLevelStr", menuLevelStr);
    }

    /**
     * 获取模板信息
     *
     * @return 模板列表
     */
    public static List<String> getTemplateList(String tplCategory) {
        List<String> templates = new ArrayList<String>();
        //java
        templates.add("vm/java/Entity.java.vm" );
        templates.add("vm/java/model/AddParamModel.java.vm" );
        templates.add("vm/java/model/EditParamModel.java.vm" );
        templates.add("vm/java/model/ExcelModel.java.vm" );
        templates.add("vm/java/model/SearchModel.java.vm" );
        templates.add("vm/java/Mapper.java.vm" );
        templates.add("vm/java/Service.java.vm" );
        templates.add("vm/java/Controller.java.vm" );
        templates.add("vm/java/xml/Mapper.xml.vm" );

        //后台管理系统
        templates.add("vm/admin/api.js.vm");
        templates.add("vm/admin/admin.vue.vm");

        //sql
        templates.add("vm/sql/sql.vm");
        return templates;
    }

    /**
     * 获取文件名
     */
    public static String getFileName(String template, CodeGenTableEntity genTable) {
        // 文件名称
        String fileName = "";
        // 包路径
        String packageName = genTable.getPackageName();
        // 大写类名
        String ClassName = genTable.getClassName();
        // 类描述
        String classRemark = genTable.getClassRemark();

        String javaPath = PROJECT_PATH + "/" + StringUtils.replace(GenConfig.basePackageName, ".", "/") + StringUtils.replace(packageName, ".", "/");
        String mybatisPath = MYBATIS_PATH + "/app";
        String vuePath = "gentable/" + classRemark;
        String sqlPath = "gentable/" + classRemark;

        if (template.contains("Entity.java.vm")) {
            fileName = StringUtils.format("{}/{}Entity.java", javaPath, ClassName);
        } else if (template.contains("AddParamModel.java.vm")) {
            fileName = StringUtils.format("{}/model/{}AddParamModel.java", javaPath, ClassName);
        } else if (template.contains("EditParamModel.java.vm")) {
            fileName = StringUtils.format("{}/model/{}EditParamModel.java", javaPath, ClassName);
        } else if (template.contains("ExcelModel.java.vm")) {
            fileName = StringUtils.format("{}/model/{}ExcelModel.java", javaPath, ClassName);
        } else if (template.contains("SearchModel.java.vm")) {
            fileName = StringUtils.format("{}/model/{}SearchModel.java", javaPath, ClassName);
        } else if (template.contains("Mapper.java.vm")) {
            fileName = StringUtils.format("{}/{}Mapper.java", javaPath, ClassName);
        } else if (template.contains("Service.java.vm")) {
            fileName = StringUtils.format("{}/{}Service.java", javaPath, ClassName);
        } else if (template.contains("Controller.java.vm")) {
            fileName = StringUtils.format("{}/{}Controller.java", javaPath, ClassName);
        } else if (template.contains("Mapper.xml.vm")) {
            fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, ClassName);
        } else if (template.contains("sql.vm")) {
            fileName = StringUtils.format("{}/{}_menu.sql", sqlPath, ClassName);
        } else if (template.contains("admin.vue.vm")) {
            fileName = StringUtils.format("{}/{}.vue", vuePath, ClassName);
        } else if (template.contains("api.js.vm")) {
            fileName = StringUtils.format("{}/{}.js", vuePath, ClassName);
        }
        return fileName;
    }

    /**
     * 获取包前缀
     *
     * @param packageName 包名称
     * @return 包前缀名称
     */
    public static String getPackagePrefix(String packageName) {
        int lastIndex = packageName.lastIndexOf(".");
        return StringUtils.substring(packageName, 0, lastIndex);
    }

    /**
     * 根据列类型获取导入包
     *
     * @param genTable 业务表对象
     * @return 返回需要导入的包列表
     */
    public static HashSet<String> getImportList(CodeGenTableEntity genTable) {
        List<CodeGenTableColumnEntity> columns = genTable.getColumns();
        CodeGenTableEntity subCodeGenTableEntity = genTable.getSubTable();
        HashSet<String> importList = new HashSet<String>();
        if (StringUtils.isNotNull(subCodeGenTableEntity)) {
            importList.add("java.util.List");
        }
        for (CodeGenTableColumnEntity column : columns) {
            if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType())) {
                importList.add("java.util.Date");
                importList.add("com.fasterxml.jackson.annotation.JsonFormat");
            } else if (!column.isSuperColumn() && GenConstants.TYPE_DOUBLE.equals(column.getJavaType())) {
                importList.add("java.math.BigDecimal");
            }
        }
        return importList;
    }

    /**
     * 根据列类型获取字典组
     *
     * @param genTable 业务表对象
     * @return 返回字典组
     */
    public static String getDicts(CodeGenTableEntity genTable) {
        List<CodeGenTableColumnEntity> columns = genTable.getColumns();
        Set<String> dicts = new HashSet<String>();
        addDicts(dicts, columns);
        if (StringUtils.isNotNull(genTable.getSubTable())) {
            List<CodeGenTableColumnEntity> subColumns = genTable.getSubTable().getColumns();
            addDicts(dicts, subColumns);
        }
        return StringUtils.join(dicts, ", ");
    }

    /**
     * 添加字典列表
     *
     * @param dicts   字典列表
     * @param columns 列集合
     */
    public static void addDicts(Set<String> dicts, List<CodeGenTableColumnEntity> columns) {
        for (CodeGenTableColumnEntity column : columns) {
            if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
                    column.getHtmlType(),
                    new String[]{GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX})) {
                dicts.add("'" + column.getDictType() + "'");
            }
        }
    }

    /**
     * 获取上级菜单ID字段
     *
     * @param paramsObj 生成其他选项
     * @return 上级菜单ID字段
     */
    public static String getParentMenuId(JSONObject paramsObj) {
        if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID)
                && StringUtils.isNotEmpty(paramsObj.getString(GenConstants.PARENT_MENU_ID))) {
            return paramsObj.getString(GenConstants.PARENT_MENU_ID);
        }
        return DEFAULT_PARENT_MENU_ID;
    }
}
